//------------------------------------------------------------------------------
///
///	\file sm-test.c
///
///	\brief
///		State Machine test harness
///
//	$Id: sm-test.c 330 2015-02-02 05:57:58Z ac.verbeck@gmail.com $
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//	The MIT License (MIT)
//
//	Copyright (c) 2014 A.C. Verbeck
//
//	Permission is hereby granted, free of charge, to any person obtaining a copy
//	of this software and associated documentation files (the "Software"), to deal
//	in the Software without restriction, including without limitation the rights
//	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//	copies of the Software, and to permit persons to whom the Software is
//	furnished to do so, subject to the following conditions:
//
//	The above copyright notice and this permission notice shall be included in
//	all copies or substantial portions of the Software.

//	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//	THE SOFTWARE.
//------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <popt.h>
#include <conio.h>

#include <stdint.h>									//	Standard int types
#include <stdbool.h>								//	Bool

#include "bi.h"
#include "debug.h"

#include "sm-auto.h"
#include "sm-full.h"

//------------------------------------------------------------------------------
// Local defines
//------------------------------------------------------------------------------
#define OPT_AUTO			0x0001
#define OPT_FULL			0x0002
#define OPT_ABOUT			0x0100
#define OPT_VERBOSE			0x0200

//------------------------------------------------------------------------------
// Local data
//------------------------------------------------------------------------------
static poptContext		optCon;

//------------------------------------------------------------------------------
// Local functions
//------------------------------------------------------------------------------
static void about(void);

//------------------------------------------------------------------------------
// Main function
//------------------------------------------------------------------------------
int main(int argc, char* argv[])
{
	uint32_t	opt=0;
	int			idx=0;
	int			in_char=0;
	bool		tr_run = true;
	bool		verbose = false;

	struct poptOption optionsTable[] = {
		{ "auto",	'u', POPT_ARG_NONE,	  NULL,			 'u', "use auto state machine",				NULL	},
		{ "full",	'f', POPT_ARG_NONE,	  NULL,			 'f', "use full state machine",				NULL	},
		{ "about",	'a', POPT_ARG_NONE,	  NULL,			 'a', "display information about the app",	NULL	},
		{ "verbose",'v', POPT_ARG_NONE,	  NULL,			 'v', "enable verbose mode",				NULL	},
		POPT_AUTOHELP
		POPT_TABLEEND
	};

//------------------------------------------------------------------------------
//  No buffering for Eclipse/CDT (bug 173732)
//
//	This won't harm anything but it's not required
//	for normal console operation.
//
//	Remove if you aren't using Eclipse/CDT.
//------------------------------------------------------------------------------
//	setvbuf(stdout, NULL, _IONBF, 0);
//	setvbuf(stdin, NULL, _IONBF, 0);

//------------------------------------------------------------------------------
//  Process arguments
//------------------------------------------------------------------------------
	optCon = poptGetContext(NULL, argc, (const char **)argv, optionsTable, 0);
	poptSetOtherOptionHelp(optCon, "[OPTIONS]*");
	if (argc == 1) {
		about();
	}
	while ((idx = poptGetNextOpt(optCon)) >= 0) {
		switch (idx) {
		case 'u':
			opt |= OPT_AUTO;
			break;
		case 'f':
			opt |= OPT_FULL;
			break;
		case 'a':
			opt |= OPT_ABOUT;
			break;
		case 'v':
			opt |= OPT_VERBOSE;
			break;
		}
	}
	if (idx < -1) {
		fprintf(stderr, "%s: %s\n",
		        poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
		        poptStrerror(idx));
		exit(opt);
	}
	if (opt & OPT_ABOUT) {
		bldinfoPrintBldInfo();
		exit(0);
	}
	if (opt & OPT_VERBOSE) {
		verbose = true;
		TRACE_init(true);
	}

//------------------------------------------------------------------------------
//  Initialize the MEI protocol state machine
//------------------------------------------------------------------------------
	if (opt & OPT_AUTO) {
		printf("state machine test: auto processing enabled\n");
		sm_auto_init();
	}
	if (opt & OPT_FULL) {
		printf("state machine test: full processing enabled\n");
		sm_full_init();
	}


//------------------------------------------------------------------------------
//  Get characters from stdin and send them to stdout
//------------------------------------------------------------------------------
	idx = 0;
	while (tr_run == true) {
		in_char = _getch();
		tr_run = (in_char == 'q') ? false : true;
		if (verbose == false)
			printf("%02x ",in_char);
		if (opt & OPT_AUTO)	sm_auto_process(in_char);
		if (opt & OPT_FULL)	sm_full_process(in_char);
	}
	printf("\nstate machine test: exiting...\n");
	return 0;
}

//------------------------------------------------------------------------------
//!	@brief
//!		Display about
//!
//!	@param
//!		none
//!
//!	@return
//!		none
//------------------------------------------------------------------------------
static void about(void)
{
	bldinfoPrintBldInfo();
	poptPrintUsage(optCon, stderr, 0);
	fflush(stdout);
	exit(1);
}

//
//  End: sm-test.c
//
